package com.github.aloxc.plugin.restplus.listener.search;

import com.github.aloxc.plugin.restplus.component.ServiceNode;
import com.github.aloxc.plugin.restplus.i18n.I18Bundle;
import com.github.aloxc.plugin.restplus.method.HttpMethod;
import com.github.aloxc.plugin.DonotGuard;
import com.github.aloxc.plugin.restplus.navigation.action.RestServiceItem;
import com.github.aloxc.plugin.restplus.navigator.RestServicesNavigator;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.ide.DataManager;
import com.intellij.ide.actions.GotoActionBase;
import com.intellij.ide.util.gotoByName.ChooseByNameFilter;
import com.intellij.ide.util.gotoByName.ChooseByNameItemProvider;
import com.intellij.ide.util.gotoByName.ChooseByNameModel;
import com.intellij.ide.util.gotoByName.ChooseByNamePopup;
import com.intellij.navigation.ChooseByNameContributor;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.datatransfer.DataFlavor;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;

/**
 * @author leero
 */
@DonotGuard
public class SearchListener extends GotoActionBase implements DumbAware, MouseListener {
    private Project project;

    public SearchListener() {
    }

    public SearchListener(Project project) {
        this.project = project;
    }

    @Override
    public void update(@NotNull AnActionEvent event) {
        super.update(event);
        event.getPresentation().setText(I18Bundle.getMessage("com.github.aloxc.plugin.restplus.toolmenu.search.text"));
    }

    @Override
    public void mouseClicked(MouseEvent e) {

        JButton button = (JButton) e.getSource();
        String place = "MainToolbar";
        Presentation presentation = new Presentation();
        DataContext dataContext = DataManager.getInstance().getDataContext(button);
//        ActionButton 128行
        //EVENT转换
        AnActionEvent event = AnActionEvent.createFromInputEvent(e, place, presentation, dataContext, false, true);
        GotoActionBase.myInAction = SearchListener.class;
        this.gotoActionPerformed(event);
    }

    @Override
    protected void gotoActionPerformed(AnActionEvent e) {
        FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.popup.service");
//
        ChooseByNameContributor[] chooseByNameContributors = {
                new SearchRequestMappingContributor(e.getData(LangDataKeys.MODULE))/*,
                new RequestMappingContributor()*/
        };

        Project project = e.getProject();
        final SearchRequestMappingModel model = new SearchRequestMappingModel(project, chooseByNameContributors);

        GotoActionCallback<HttpMethod> callback = new GotoActionCallback<HttpMethod>() {
            @Override
            protected ChooseByNameFilter<HttpMethod> createFilter(@NotNull ChooseByNamePopup popup) {
                return new SearchListener.GotoRequestMappingFilter(popup, model, project);
            }

            @Override
            public void elementChosen(ChooseByNamePopup chooseByNamePopup, Object element) {
                if (element instanceof RestServiceItem) {
                    RestServiceItem navigationItem = (RestServiceItem) element;
                    RestServicesNavigator servicesNavigator = project.getComponent(RestServicesNavigator.class);
                    TreeModel treeModel = servicesNavigator.getUrlTree().getModel();
                    TreePath treePath = find((DefaultMutableTreeNode) treeModel.getRoot(), navigationItem);
                    if (treePath != null) {
                        expandAll(servicesNavigator.getUrlTree(), new TreePath(treeModel.getRoot()), true);
                        servicesNavigator.getUrlTree().setSelectionPath(treePath);
                        servicesNavigator.getUrlTree().scrollPathToVisible(treePath);
                    }
                    if (!navigationItem.isSwagger() && navigationItem.canNavigate()) {
                        navigationItem.navigate(true);

                    }
                }
            }
        };

        SearchRequestMappingProvider provider = new SearchRequestMappingProvider(getPsiContext(e));
        showNavigationPopup(e, model, callback, "Request Mapping Url matching pattern", true, true, (ChooseByNameItemProvider) provider);
    }

    private void expandAll(JTree tree, TreePath parent, boolean expand) {
        TreeNode node = (TreeNode) parent.getLastPathComponent();
        if (node.getChildCount() > 0) {
            for (Enumeration e = node.children(); e.hasMoreElements(); ) {
                TreeNode n = (TreeNode) e.nextElement();
                TreePath path = parent.pathByAddingChild(n);
                expandAll(tree, path, expand);

            }
        }
        if (expand) {
            tree.expandPath(parent);
        } else {
            tree.collapsePath(parent);
        }
    }

    private TreePath find(DefaultMutableTreeNode root, RestServiceItem serviceItem) {
        @SuppressWarnings("unchecked")
        Enumeration<TreeNode> e = root.depthFirstEnumeration();
        while (e.hasMoreElements()) {
            DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) e.nextElement();
            if (treeNode instanceof ServiceNode) {
                ServiceNode node = (ServiceNode) treeNode;
                if(node.isSwagger() != serviceItem.isSwagger()){
                    continue;
                }
                if(node.isSwagger()) {
                    if (node.getRestServiceItem().getUrl().equalsIgnoreCase(serviceItem.getUrl())
                            && serviceItem.getMethod() == node.getRestServiceItem().getMethod()
                            && serviceItem.getParentName().equals(node.getRestServiceItem().getParentName())
                    ) {
                        return new TreePath(node.getPath());
                    }
                }else{
                    if (node.getRestServiceItem().getUrl().equalsIgnoreCase(serviceItem.getUrl())
                            && serviceItem.getMethod() == node.getRestServiceItem().getMethod()
                            && serviceItem.getModule().getName().equals(node.getRestServiceItem().getModule().getName())
                    ) {
                        return new TreePath(node.getPath());
                    }
                }
            }
        }
        return null;
    }

    /**
     * TODO IDEA 2018 删了？
     *
     * @param e
     * @param model
     * @param callback
     * @param findUsagesTitle
     * @param useSelectionFromEditor
     * @param allowMultipleSelection
     * @param itemProvider
     * @param <T>
     */
    @Override
    protected <T> void showNavigationPopup(AnActionEvent e,
                                           ChooseByNameModel model,
                                           final GotoActionCallback<T> callback,
                                           @Nullable final String findUsagesTitle,
                                           boolean useSelectionFromEditor,
                                           final boolean allowMultipleSelection,
                                           final ChooseByNameItemProvider itemProvider) {
        final Project project = e.getData(CommonDataKeys.PROJECT);
        boolean mayRequestOpenInCurrentWindow = model.willOpenEditor() && FileEditorManagerEx.getInstanceEx(project).hasSplitOrUndockedWindows();
        Pair<String, Integer> start = getInitialText(useSelectionFromEditor, e);


        String copiedUrl = tryFindCopiedUrl();

        String predefinedText = start.first == null ? copiedUrl : start.first;

        showNavigationPopup(callback, findUsagesTitle,
                SearchServiceChooseByNamePopup.createPopup(project, model, itemProvider, predefinedText,
                        mayRequestOpenInCurrentWindow,
                        start.second), allowMultipleSelection);
    }

    private String tryFindCopiedUrl() {
        String contents = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
        if (contents == null) {
            return null;
        }

        contents = contents.trim();
        if (contents.startsWith("http")) {
            if (contents.length() <= 120) {
                return contents;
            } else {
                return contents.substring(0, 120);
            }
        }

        return null;
    }


    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }


/*
    private class GotoRequestMappingCallback extends GotoActionCallback{
//        定位选择文件
        @Override
        public void elementChosen(ChooseByNamePopup chooseByNamePopup, Object element) {
            if (element instanceof RestServiceItem) {
                RestServiceItem navigationItem = (RestServiceItem) element;
                if (navigationItem.canNavigate()) {
                    navigationItem.navigate(true);
                }
            }
        }
    }*/

    protected static class GotoRequestMappingFilter extends ChooseByNameFilter<HttpMethod> {
        GotoRequestMappingFilter(final ChooseByNamePopup popup, SearchRequestMappingModel model, final Project project) {
            super(popup, model, SearchRequestMappingConfiguration.getInstance(project), project);
        }

        @Override
        @NotNull
        protected List<HttpMethod> getAllFilterValues() {
//            List<HttpMethod> elements = new ArrayList<>();
            /*elements.add(HttpMethod.GET);
            elements.add(HttpMethod.POST);
            elements.add(HttpMethod.DELETE);
            elements.add(HttpMethod.PATCH);*/
            List<HttpMethod> elements = Arrays.asList(HttpMethod.values());

            return elements;
        }

        @Override
        protected String textForFilterValue(@NotNull HttpMethod value) {
            return value.name();
        }

        @Override
        protected Icon iconForFilterValue(@NotNull HttpMethod value) {
//            return value.getIcon();
            return null;
        }
    }


    /**
     * 找到文件
     *
     * @param element
     * @param chooseByNamePopup
     * @return
     */
    private PsiElement getElement(PsiElement element, ChooseByNamePopup chooseByNamePopup) {
        return null;
    }
}